package com.tan.lbs.dao.impl;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;

import com.tan.lbs.dao.DialogNodeOrderDAO;
import com.tan.lbs.entity.DialogNode;
import com.tan.lbs.entity.DialogNodeInTree;
import com.tan.lbs.entity.DialogNodeOrder;
import com.tan.lbs.entity.Item;
import com.tan.lbs.util.HibernateUtil;

public class DialogNodeOrderDAOImpl implements DialogNodeOrderDAO{
	
	//public static int MAX_CHILD_NODES_NUM = 4; 

	@Override
	public String create(DialogNodeOrder dialogNodeOrder) {
		SessionFactory sf = HibernateUtil.getSessionFactory();
		Session s = sf.getCurrentSession();
		s.beginTransaction();
		s.save(dialogNodeOrder);
		s.getTransaction().commit();
		return dialogNodeOrder.getOrderID();
	}

	@Override
	public DialogNodeOrder readByID(String orderID) {
		SessionFactory sf = HibernateUtil.getSessionFactory();
		Session s = sf.getCurrentSession();
		s.beginTransaction();
		DialogNodeOrder dialogNodeOrder = (DialogNodeOrder)s.get(DialogNodeOrder.class, orderID);
		s.getTransaction().commit();
		return dialogNodeOrder;
	}

	@Override
	public void update(DialogNodeOrder dialogNodeOrder) {
		SessionFactory sf = HibernateUtil.getSessionFactory();
		Session s = sf.getCurrentSession();
		s.beginTransaction();
		s.update(dialogNodeOrder);
		s.getTransaction().commit();
	}

	@Override
	public void delete(String orderID) {
		SessionFactory sf = HibernateUtil.getSessionFactory();
		Session s = sf.getCurrentSession();
		s.beginTransaction();
		DialogNodeOrder dialogNodeOrder = new DialogNodeOrder();
		dialogNodeOrder.setOrderID(orderID);
		s.delete(dialogNodeOrder);
		s.getTransaction().commit();	
	}

	@Override
	public ArrayList<DialogNodeOrder> searchByNPC(String npcID) {
		SessionFactory sf = HibernateUtil.getSessionFactory();
		Session s = sf.getCurrentSession();
		s.beginTransaction();
		List<DialogNodeOrder> gs = s.createCriteria(DialogNodeOrder.class).add(Restrictions.
				eq("npcID", npcID)).list();
		s.getTransaction().commit();
		return new ArrayList<DialogNodeOrder>(gs);
	}

	@Override
	public DialogNodeInTree searchByNPCInTreeByStartDialogNode(String rootStartDialogNodeID) {
		SessionFactory sf = HibernateUtil.getSessionFactory();
		Session session = sf.getCurrentSession();
		session.beginTransaction();
		DialogNodeInTree tree = recursiveGetNodes(session,rootStartDialogNodeID);
		session.getTransaction().commit();
		return tree;
	}
	
	private DialogNodeInTree recursiveGetNodes(Session session, String fromDialogNodeID) {
		if(fromDialogNodeID!=null) {
		DialogNode dialogNode = (DialogNode)session.get(DialogNode.class, fromDialogNodeID);
		List<DialogNodeOrder> ds = session.createCriteria(DialogNodeOrder.class).add(Restrictions.
				eq("fromNodeID", fromDialogNodeID)).list();
		DialogNodeInTree tree = new DialogNodeInTree();
		tree.setID(fromDialogNodeID);
		tree.setName(dialogNode.getName());
		if(ds.size() > 3) 
			tree.setNode4(recursiveGetNodes(session,ds.get(3).getToNodeID()));
		if(ds.size() > 2)
			tree.setNode3(recursiveGetNodes(session,ds.get(2).getToNodeID()));
		if(ds.size() > 1)
			tree.setNode2(recursiveGetNodes(session,ds.get(1).getToNodeID()));
		if(ds.size() > 0)
			tree.setNode1(recursiveGetNodes(session,ds.get(0).getToNodeID()));
		return tree;
		} 
		return null;
	}

	@Override
	public ArrayList<DialogNodeOrder> searchByFromDialogNode(String fromNodeID) {
		SessionFactory sf = HibernateUtil.getSessionFactory();
		Session s = sf.getCurrentSession();
		s.beginTransaction();
		List<DialogNodeOrder> gs = s.createCriteria(DialogNodeOrder.class).add(Restrictions.
				eq("fromNodeID", fromNodeID)).list();
		s.getTransaction().commit();
		return new ArrayList<DialogNodeOrder>(gs);
	}

	@Override
	public DialogNodeOrder readByToNode(String toNodeID) {
		SessionFactory sf = HibernateUtil.getSessionFactory();
		Session s = sf.getCurrentSession();
		s.beginTransaction();
		List<DialogNodeOrder> gs = s.createCriteria(DialogNodeOrder.class).add(Restrictions.
				eq("toNodeID", toNodeID)).list();
		s.getTransaction().commit();
		if(gs.size() > 0) return gs.get(0);
		else return null;
	}

	@Override
	public void deleteAllChildrenUnderDialogNode(String deleteStartDialogNodeID) {
		SessionFactory sf = HibernateUtil.getSessionFactory();
		Session session = sf.getCurrentSession();
		session.beginTransaction();
		recursiveDeleteNodes(session,deleteStartDialogNodeID);
		session.getTransaction().commit();
		
	}

	private void recursiveDeleteNodes(Session session,
			String deleteStartDialogNodeID) {
		List<DialogNodeOrder> nodes = session.createCriteria(DialogNodeOrder.class).add(Restrictions.
				eq("fromNodeID", deleteStartDialogNodeID)).list();
		if(nodes.size() == 0) {
			DialogNode dialogNode = new DialogNode();
			dialogNode.setDialogNodeID(deleteStartDialogNodeID);
			session.delete(dialogNode);
			return;
		}
		else {
			for(int i = 0; i < nodes.size(); ++i) {
				recursiveDeleteNodes(session,nodes.get(i).getToNodeID());
				session.delete(nodes.get(i));
			}
		}
		
	}

}
